package cn.tedu.threadpool;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

public class ForkJoinPoolDemo {

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        // 需求：求1-100000000000L的和

        // 主函数所在的类默认就是一个线程类 - 主线程
        // 一个线程只能被分配到一个CPU核上来运行
        // 现在开发中，CPU是多核的
        long begin = System.currentTimeMillis();

        // 38190
        // long sum = 0;
        // for (long i = 1; i <= 100000000000L; i++) {
        //     sum += i;
        // }
        // System.out.println(sum);

        // 30941
        ForkJoinPool pool = new ForkJoinPool();
        ForkJoinTask<Long> f = pool.submit(new Sum(1, 100000000000L));
        System.out.println(f.get());
        pool.shutdown();

        long end = System.currentTimeMillis();
        System.out.println(end - begin);

    }

}

// 泛型定义的是结果类型
class Sum extends RecursiveTask<Long> {

    private final long start;
    private final long end;

    public Sum(long start, long end) {
        this.start = start;
        this.end = end;
    }

    // 分叉合并的计算逻辑就是覆盖在这个方法中的
    @Override
    protected Long compute() {

        if (end - start <= 10000) {
            // 如果这个范围内不到10000个数，那么认为这个范围内的数字相对已经比较少了
            // 那么需要将这个小范围内的数字求和
            long sum = 0;
            for (long i = start; i <= end; i++) {
                sum += i;
            }
            return sum;
        } else {
            // 这个范围内的数字超过10000个了，范围依然比较大
            // 如果范围比较大，就继续拆分
            long mid = (start + end) / 2;
            Sum left = new Sum(start, mid);
            Sum right = new Sum(mid + 1, end);
            // 分叉
            // 表示将这个left定义为单独的任务
            left.fork();
            right.fork();
            // 合并
            return left.join() + right.join();
        }

    }
}